using System;
using System.Collections;
using System.Data;
using System.Text;
using System.Web;
using System.Web.UI.WebControls;
using PHSRAG.Insight21.Common.Pages;
using PHSRAG.Insight21.Context;
using PHSRAG.Insight21.InsightWebControls;
using PHSRAG.Insight21.Personnel;
using PHSRAG.Insight21.Policy;
using PHSRAG.Insight21.SearchContext;
using PHSRAG.Utility;
using PHSRAG.WebControls;
using Summary = PHSRAG.Insight21.Personnel.PersonnelSummary;
using PersonnelConstants = PHSRAG.Insight21.Personnel.Constants;

namespace PHSRAG.Insight21
{
    /// <summary>
    /// The PersonnelSummary class supports the PersonnelSummary.aspx page.
    /// It displays the summary view for all the personnel the currently loggedin user has access to.
    /// It also allows the user to drill down to the salary grid or the personnel details page.
    /// </summary>
    /// <remarks>
    /// The PersonnelSummary page supports searching/filtering the personnel summary data
    /// based on user-defined and user-selectable search criteria.
    /// Following is the list of such criteria:
    /// <list type="bullet">
    /// <item><description>Employee Last Name (free-form entry)</description></item>
    /// <item><description>Employee First Name (free-form entry)</description></item>
    /// <item><description>PI (select from a DataGrid)</description></item>
    /// <item><description>Lab (select from a DataGrid)</description></item>
    /// <item><description>Employee Number (free-form entry)</description></item>
    /// <item><description>Job Code (free-form entry)</description></item>
    /// <item><description>Status (select from a drop-down list)</description></item>
    /// <item><description>HR Department (select from a drop-down list)</description></item>
    /// <item><description>Pay Frequency type (select from a drop-down list)</description></item>
    /// <item><description>Effective Salary Date From/To (select both from a calender)</description></item>
    /// <item><description>Fund Ending Date (select from a drop-down list)</description></item>
    /// </list>
    /// </remarks>
    public partial class PersonnelSummary : NoCachePage
    {
        #region Constants

        private const string AllocationErrorStyle = "DataGridNegativeCurrencyItem";
        private const string AnnualRateCommandName = "SelectSalary";
        private const string CurrentPageIndexKey = "CurrentPageIndex_5B40975C-13DE-4161-AF82-5A5119C877DB";
        private const string EmployeeIDCommandName = "SelectEmployeeID";
        private const string EmployeeNameCommandName = "SelectEmployeeName";
        private const int FirstChildControlIndex = 0;
        private const string SearchCriteriaVersionKey = "SearchCriteriaVersion_2C933E84-632E-4949-8010-65481CCFE43F";

        #endregion

        #region Enumerations (Private)

        /// <summary>
        /// The DataGridColumns enumeration defines values 
        /// for indexing columns in the datagrid.
        /// </summary>
        private enum DataGridColumns
        {
            EmployeeJobMapId,
            EmployeeNumber,
            RecordNumber,
            Status,
            Division,
            Name,
            //LastName,
            //FirstName,
            PayType,
            JobCode,
            AnnualRate,
            EffectiveDate
        }

        #endregion

        #region Instance Variables (Private)

        private ICachePolicy cachePolicy;
        protected Label numberOfRecords;
        private ICachePolicy pageCachePolicy;

        #endregion

        #region Private Properties

        /// <summary>
        /// Get the personnel summary informations that the logged-in user has access to. The list of personnel summaries is
        /// is maintained by the PersonnelSummaries business object within its data container. This object is cached.
        /// </summary>
        private PersonnelSummaries PersonnelSummariesInstance
        {
            get
            {
                PersonnelSummaries personnelSummaries =
                    ResultsCache.GetObject(cachePolicy, PersonnelSummaries.CacheKey) as PersonnelSummaries;

                if (personnelSummaries == null)
                {
                    personnelSummaries = new PersonnelSummaries();
                    personnelSummaries.Load(DataAccess.GetConnectionString()
                        , ((UserContext) cachePolicy.GetCachedObject(UserContext.CacheKey)).DomainUserId);
                    ResultsCache.SetObject(cachePolicy, PersonnelSummaries.CacheKey, personnelSummaries);
                }

                return personnelSummaries;
            }
        }

        /// <summary>
        /// Gets/sets an integer value indicating the search criteria version. 
        /// The version number changes when the search criteria changes.  This signals the page to re-build its
        /// cache.
        /// </summary>
        private int SearchCriteriaVersion
        {
            get
            {
                Hashtable h = pageCachePolicy.GetCachedObject(Keys.AgreementSummaryPageKey) as Hashtable;
                return (h == null || h[SearchCriteriaVersionKey] == null) ? 0 : (int) h[SearchCriteriaVersionKey];
            }
            set
            {
                Hashtable h = pageCachePolicy.GetCachedObject(Keys.AgreementSummaryPageKey) as Hashtable ?? new Hashtable();

                h[SearchCriteriaVersionKey] = value;
                pageCachePolicy.Cache(Keys.AgreementSummaryPageKey, h);
            }
        }

        /// <summary>
        /// Get/Set the current page within the datagrid for display. This information persists across page loads.
        /// This information is cached using the page cache policy
        /// Get: Return the value from the page cache policy, returns 0 if its not present in cache
        /// Set: Set the value and update the cache
        /// </summary>
        private int CurrentPageIndex
        {
            get
            {
                Hashtable h = pageCachePolicy.GetCachedObject(Keys.PersonnelSummaryPageKey) as Hashtable;
                return (h == null || h[CurrentPageIndexKey] == null) ? 0 : (int) h[CurrentPageIndexKey];
            }
            set
            {
                Hashtable h = pageCachePolicy.GetCachedObject(Keys.PersonnelSummaryPageKey) as Hashtable ?? new Hashtable();
                h[CurrentPageIndexKey] = value;
                personnelSummaryGrid.CurrentPageIndex = value;
                pageCachePolicy.Cache(Keys.PersonnelSummaryPageKey, h);
            }
        }

        #endregion

        #region Constructors

        #endregion

        #region Event Handlers

        #region Page load

        /// <summary>
        /// Handler for the event raised when the page is being loaded.
        /// Initialize the bread crumb control, set the page size for the data grid, and load the data grid with data.
        /// </summary>
        /// <param name="sender">Control which raised the event</param>
        /// <param name="e">Argument associated with the event</param>
        protected void Page_Load(object sender, EventArgs e)
        {
            annunciator.Message = string.Empty;
            annunciator.Title = string.Empty;

            breadCrumb.Add("Personnel Summary", Settings.
                GetKeyValue("SubNavigation.Personnel.PersonnelSummaryURL", string.Empty),
                Constants.DefaultSummaryPageRank);
            reportDownload.SQLReportName = SSRSRequest.ReportNames.Personnel.PersonnelSummary; //"Personnel_PersonnelSummary"
            if (!IsPostBack)
            {
                ((ExpansionToggler) expandingPanel.FindControl("expansionToggler")).HelpText =
                    InsightUtilities.Constants.SearchHelpText;

                personnelSummaryGrid.PageSize = Settings.GetKeyValue(Constants.DataGridPageSizeKey,
                    Constants.DefaultDatagridPageSize);
                ProcessSearchIni();
            }
            personnelSubNavigation.SelectedLink = PersonnelSubNavigation.personnelSummaryCommand;
            //added expanded panel as requested in TrackIt 6940 10/22/2007 JML:
            expandingPanel.IsExpanded = true;

            hiddenSearchCriteria.Value = HttpUtility.UrlEncode(AddRefreshDatesToCriteria(((CommonSearchContext) cachePolicy.GetCachedObject(CommonSearchContext.CacheKey)).GetSearchCriteria(Page.Request.Url.ToString())));
        }

        #endregion

        #region Datagrid event handlers

        /// <summary>
        /// Handler for event raised while each data grid item is created.
        /// Help in putting the symbol denoting the sort column in the data grid.
        /// If the item being created is the data grid header:
        /// <list type="bullet">
        /// <item><description>Get the sort column and sort order from the PersonnelSummaries instance in the cache</description></item>
        /// <item><description>Create a Hashtable of column indices, keyed by the sort expression of each column</description></item>
        /// <item><description>Using the hash table add a label with sort symbol to the column on which sort has happened</description></item>
        /// </list>
        /// </summary>
        /// <param name="sender">Control which raised the event</param>
        /// <param name="e">Argument associated with the event</param>
        protected void OnItemCreated(object sender, DataGridItemEventArgs e)
        {
            if (e.Item.ItemType == ListItemType.Header)
            {
                PersonnelSummaries personnelSummaries = PersonnelSummariesInstance;
                Label sortSymbol = new Label();
                sortSymbol.Text = personnelSummaries.SortAscending ? InsightUtilities.Constants.SortAscendingText : InsightUtilities.Constants.SortDescendingText;
                sortSymbol.Font.Name = InsightUtilities.Constants.SortSymbolFontName;

                Hashtable columnMap = new Hashtable();
                foreach (DataGridColumn column in personnelSummaryGrid.Columns)
                {
                    columnMap[column.SortExpression] = personnelSummaryGrid.Columns.IndexOf(column);
                }

                string sortColumn = personnelSummaries.SortColumn;
                if (columnMap.ContainsKey(sortColumn))
                {
                    (e.Item.Cells[(int) columnMap[sortColumn]]).Controls.Add(sortSymbol);
                }
            }
        }

        /// <summary>
        /// Handler for the event raised when a column header within the data grid is clicked.
        /// Set the currentpageindex to 0 as sorting need to be done on all records and not only on what is visible
        /// Load the data grid and intialize the pager controls
        /// </summary>
        /// <param name="sender">Control which raised the event</param>
        /// <param name="e">Argument associated with the event</param>
        protected void OnSort(object sender, DataGridSortCommandEventArgs e)
        {
            if (e.SortExpression != string.Empty)
            {
                PersonnelSummariesInstance.Sort(e.SortExpression);
                CurrentPageIndex = 0;
                LoadDataGrid();
            }
        }

        /// <summary>
        /// Handler for the event raised when a row in the datagrid is databound.
        /// Check for the error flag and format the AnnualRate column accordingly.
        /// </summary>
        /// <param name="sender">Control which raised the event</param>
        /// <param name="e">Argument associated with the event</param>
        protected void OnItemDataBound(object sender, DataGridItemEventArgs e)
        {
            try
            {
                if (e.Item.ItemType == ListItemType.Item || e.Item.ItemType == ListItemType.AlternatingItem)
                {
                    Summary personnelSummary = (Summary) e.Item.DataItem;
                    if (personnelSummary.ErrorFlag)
                    {
                        e.Item.Cells[(int) DataGridColumns.AnnualRate].CssClass = AllocationErrorStyle;
                    }
                }
            }
            catch (Exception ex)
            {
                Utility.ExceptionReport.WriteToEventLog("Personnel Summary", ex,
                    true, Utility.ExceptionReport.ReportType.Error);
                annunciator.Message = "Error while attempting to format columns.";
            }
        }

        /// <summary>
        /// Handler for the event raised when a row in the datagrid is clicked upon.
        /// If the "EmployeeId" was clicked upon (its CommandName is "SelectEmployeeID"), load the PersonnelDetails page
        /// If the "Last Name" or "First Name" was clicked upon(its CommandName is "SelectEmployeeName"), load the PerDetails page
        /// If the "AnnualRate" was clicked upon (its CommandName is "SelectSalary"), load the SalaryGrid page
        /// In all the cases the page passes the selected employee's jobmapid through a dictionary.
        /// </summary>
        /// <param name="sender">Control which raised the event</param>
        /// <param name="e">Argument associated with the event</param>
        protected void OnDataGridItemCommand(object sender, DataGridCommandEventArgs e)
        {
            try
            {
                if ((e.Item.ItemType == ListItemType.Item) || (e.Item.ItemType == ListItemType.AlternatingItem))
                {
                    Hashtable dictionary = new Hashtable();
                    dictionary.Add(Keys.EmployeeJobMapIDKey,
                        Convert.ToInt32(e.Item.Cells[(int) DataGridColumns.EmployeeJobMapId].Text));
                    pageCachePolicy.Cache(Keys.IncomingDataKey, dictionary);

                    if (e.CommandName == EmployeeIDCommandName || e.CommandName == EmployeeNameCommandName)
                    {
                        PurgeCache();
                        Response.Redirect
                            (Settings.GetKeyValue("Other.Personnel.PersonnelDetailsURL", string.Empty), false);
                    }
                    else if (e.CommandName == AnnualRateCommandName)
                    {
                        PurgeCache();
                        Response.Redirect
                            (Settings.GetKeyValue("SubNavigation.Personnel.SalaryGridURL", string.Empty), false);
                    }
                }
            }
            catch (Exception ex)
            {
                Utility.ExceptionReport.WriteToEventLog("Personnel Summary", ex,
                    true, Utility.ExceptionReport.ReportType.Error);
                annunciator.Message = string.Format
                    ("Error while attempting to navigate for {0} click", e.CommandName);
            }
        }

        #endregion

        #region Paging event handlers

        /// <summary>
        /// Handler for the event raised when the FirstPage link is clicked in the Pager control.
        /// Set the current page index to 0, bind the datagrid with data and manage navigation links.
        /// To avoid superfluous data binding activites, no action is taken if the current page index is already 0.
        /// </summary>
        /// <param name="sender">Control which rasied the event</param>
        /// <param name="e">Arguments associated with the event</param>
        protected void OnFirstPage(object sender, CommandEventArgs e)
        {
            CurrentPageIndex = 0;
            LoadDataGrid();
        }

        /// <summary>
        /// Handler for the event raised when the LastPage link is clicked in the Pager control.
        /// Set the current page index to one less than the total page count (index is 0-based), bind the datagrid with
        /// data and manage navigation links.
        /// To avoid superfluous data binding activites, no action is taken if the current 
        /// page index is already corresponding to the last page.
        /// </summary>
        /// <param name="sender">Control which rasied the event</param>
        /// <param name="e">Arguments associated with the event</param>
        protected void OnLastPage(object sender, CommandEventArgs e)
        {
            CurrentPageIndex = pagerAboveDatagrid.PageCount - 1;
            LoadDataGrid();
        }

        /// <summary>
        /// Handler for the event raised when the NextPage link is clicked in the Pager control.
        /// Increment the current page index, bind the datagrid with data and manage navigation links.
        /// </summary>
        /// <param name="sender">Control which rasied the event</param>
        /// <param name="e">Arguments associated with the event</param>
        protected void OnNextPage(object sender, CommandEventArgs e)
        {
            ++CurrentPageIndex;
            LoadDataGrid();
        }

        /// <summary>
        /// Handler for the event raised when the PreviousPage link is clicked in the Pager control.
        /// Decrement the current page index, bind the datagrid with data and manage navigation links.
        /// </summary>
        /// <param name="sender">Control which rasied the event</param>
        /// <param name="e">Arguments associated with the event</param>
        protected void OnPreviousPage(object sender, CommandEventArgs e)
        {
            --CurrentPageIndex;
            LoadDataGrid();
        }

        #endregion

        #region Search event handler

        /// <summary>
        /// Handler for the event raised when the Search button is clicked in the Search control.
        /// Gets the search criteia and performs a search. The actual search is performed by the PersonnelSummaries object
        /// which returns true if it did indeed apply any filteration criteria, and false otherwise. This predicate
        /// is used by LoadDataGrid() to control the visibility of the pager controls.
        /// </summary>
        /// <param name="args">Search Criteria args associated with the search event</param>
        protected void OnSearch(SearchCriteriaArgs args)
        {
            CurrentPageIndex = 0;
            ProcessSearch();
        }

        /// <summary>
        /// Handler for the event raised when the "Clear Selection" button is clicked on the page.
        /// </summary>
        /// <param name="sender">Control which raised the event</param>
        /// <param name="e">Argument associated with the event</param>
        protected void OnClearSelection(object sender, CommandEventArgs e)
        {
            personnelSummaryGrid.Visible = false;
            pagerAboveDatagrid.Visible = pagerBelowDatagrid.Visible = false;
        }

        #endregion

        #region Downloadbar event handlers

        /// <summary>
        /// Invoked by the download bar when it catches an exception.
        /// </summary>
        /// <param name="sender">Control which raised the event</param>
        /// <param name="e">Argument associated with the event</param>
        protected void OnDownloadFailed(object sender, CommandEventArgs e)
        {
            annunciator.Title = "Following error(s) occurred while downloading";
            annunciator.Message = Utility.ExceptionReport.GetExceptionInfo((Exception) e.CommandArgument, false);
        }

        #endregion

        #region Header

        /// <summary>
        /// Resets the subnavigation selected link(s) before the 
        /// header performs a redirect.
        /// </summary>
        /// <param name="sender">Control which rasied the event.</param>
        /// <param name="e">Arguments associated with the event.</param>
        protected void OnHeaderNavigate(object sender, CommandEventArgs e)
        {
            personnelSubNavigation.Reset();
            PurgeCache();
        }

        #endregion

        #endregion

        #region Private Methods

        /// <summary>
        /// Load the datagrid with sufficient data for display within one page of the data grid. This is done as follows:
        /// Get the summaries for all personnel that the user has access to. Use that to initialize the data grid and
        /// the pager controls based on the page size of the data grid.
        /// The pagers are made visible only when more than one page of data can be displayed.
        /// If there is no data to display, warn the user via the annunciator.
        /// </summary>
        private void LoadDataGrid()
        {
            try
            {
                PersonnelSummaries personnelSummaries = PersonnelSummariesInstance;

                personnelSummaryGrid.VirtualItemCount = pagerAboveDatagrid.RecordCount
                    = pagerBelowDatagrid.RecordCount = personnelSummaries.Count;

                int currentPageIndex = CurrentPageIndex;
                int pageCount = (pagerAboveDatagrid.RecordCount/personnelSummaryGrid.PageSize) +
                    (((pagerAboveDatagrid.RecordCount%personnelSummaryGrid.PageSize) == 0) ? 0 : 1);
                pagerBelowDatagrid.PageCount = pagerAboveDatagrid.PageCount = pageCount;
                pagerBelowDatagrid.CurrentPage = pagerAboveDatagrid.CurrentPage = currentPageIndex + 1;

                personnelSummaryGrid.DataSource = personnelSummaries.GetPersonnelSummaryList
                    (currentPageIndex*personnelSummaryGrid.PageSize, personnelSummaryGrid.PageSize);
                personnelSummaryGrid.DataBind();

                personnelSummaryGrid.Visible = pagerBelowDatagrid.Visible = pagerAboveDatagrid.Visible =
                    (personnelSummaryGrid.Items.Count > 0);
                if (pagerAboveDatagrid.Visible)
                {
                    ManagePagination();
                }
                else
                {
                    annunciator.Message = "No personnel data found for user";
                }
            }
            catch (Exception ex)
            {
                personnelSummaryGrid.Visible = pagerBelowDatagrid.Visible = pagerAboveDatagrid.Visible = false;
                annunciator.Message = Utility.ExceptionReport.GetExceptionInfo(ex, false);
            }
        }

        /// <summary>
        /// Manages the pagination logic.
        /// Set the First record and last record values for the pager controls
        /// based on the current page index and the data grid page size respectively
        /// Determines which links should be active and which should be inactive
        /// for the first page and last page links.
        /// </summary>
        private void ManagePagination()
        {
            int currentPageIndex = CurrentPageIndex;
            personnelSummaryGrid.CurrentPageIndex = currentPageIndex;

            int startIndex = currentPageIndex*personnelSummaryGrid.PageSize;

            pagerBelowDatagrid.FirstRecord = pagerAboveDatagrid.FirstRecord = startIndex + 1;
            pagerBelowDatagrid.LastRecord = pagerAboveDatagrid.LastRecord =
                Math.Min(startIndex + personnelSummaryGrid.PageSize, personnelSummaryGrid.VirtualItemCount);

            pagerBelowDatagrid.EnableFirstPage = pagerAboveDatagrid.EnableFirstPage =
                pagerBelowDatagrid.EnablePreviousPage = pagerAboveDatagrid.EnablePreviousPage =
                    (CurrentPageIndex != 0);

            pagerBelowDatagrid.EnableLastPage = pagerAboveDatagrid.EnableLastPage =
                pagerBelowDatagrid.EnableNextPage = pagerAboveDatagrid.EnableNextPage =
                    (CurrentPageIndex != (pagerAboveDatagrid.PageCount - 1));
        }

        /// <summary>
        /// Adds refresh dates currently visible on the page to the search criteria string
        /// to be passed down to reports. The criteria does not persist to the SearchCriteria
        /// object.
        /// </summary>
        /// <param name="searchCriteria">Object containing search criteria.</param>
        /// <returns>A string representation of search criteria. </returns>
        private string AddRefreshDatesToCriteria(SearchCriteria searchCriteria)
        {
            StringBuilder criteria = new StringBuilder(searchCriteria.ToString(";"));
            if (refreshDates.SalaryAsOfDateVisible)
            {
                criteria.AppendFormat("Last Salary Post|{0};", refreshDates.SalaryAsOfDate.ToShortDateString());
            }
            if (refreshDates.GLAsOfDateVisible)
            {
                criteria.AppendFormat("Last GL Post|{0};", refreshDates.GLPostAsOfDate.ToShortDateString());
            }
            if (refreshDates.POAPAsOfDateVisible)
            {
                criteria.AppendFormat("Last PO/AP Post|{0};", refreshDates.POAPAsOfDate.ToShortDateString());
            }
            return criteria.ToString();
        }

        /// <summary>
        /// Search the summary data for the specified search criteria
        /// </summary>
        private void ProcessSearch()
        {
            try
            {
                CommonSearchContext searchContext = (CommonSearchContext) cachePolicy.GetCachedObject(CommonSearchContext.CacheKey);
                SearchCriteria searchCriteria = searchContext.GetSearchCriteria(Page.Request.Url.ToString());
                int searchVersion = searchCriteria.Version;

                PersonnelSummariesInstance.
                    Search(((CommonSearchContext) cachePolicy.GetCachedObject(CommonSearchContext.CacheKey)).GetSearchCriteria(Page.Request.Url.ToString()));
                if (searchVersion != SearchCriteriaVersion)
                {
                    CurrentPageIndex = 0;
                    SearchCriteriaVersion = searchVersion;
                }

                LoadDataGrid();

                hiddenSearchCriteria.Value = HttpUtility.UrlEncode(AddRefreshDatesToCriteria(searchCriteria));
            }
            catch (Exception ex)
            {
                annunciator.Message = Utility.ExceptionReport.GetExceptionInfo(ex, false);
            }
        }

        //--added to force initial selection with Status = "Active"
        //Requested in TrackIt 6940. 10/30/2007 JML.
        //---------------------------------------------------------
        private void ProcessSearchIni()
        {
            try
            {
                CommonSearchContext searchContext = (CommonSearchContext) cachePolicy.GetCachedObject(CommonSearchContext.CacheKey);
                SearchCriteria searchCriteria = searchContext.GetSearchCriteria(Page.Request.Url.ToString());
                int searchVersion = searchCriteria.Version;

                PersonnelSearchContext personnelSearchContext = (PersonnelSearchContext) cachePolicy.GetCachedObject(PersonnelSearchContext.CacheKey);
                DataRow[] dataRows = personnelSearchContext.StatusData.Select("ID=1");
                if (dataRows.Length > 0)
                {
                    string awardedText = dataRows[0]["Description"].ToString();
                    if (searchCriteria[InsightUtilities.Constants.StatusIDKey] == null)
                    {
                        searchContext.SetPrimarySearchCriteria(SearchCriteria.Level.Summary,
                            Page.Request.Url.ToString(),
                            InsightUtilities.Constants.StatusIDKey, "1", "Status",
                            CommonSearch.LabelValueSeparator, awardedText);
                    }
                }

                PersonnelSummariesInstance.
                    Search(((CommonSearchContext) cachePolicy.GetCachedObject(CommonSearchContext.CacheKey)).GetSearchCriteria(Page.Request.Url.ToString()));
                if (searchVersion != SearchCriteriaVersion)
                {
                    CurrentPageIndex = 0;
                    SearchCriteriaVersion = searchVersion;
                }

                LoadDataGrid();
            }
            catch (Exception ex)
            {
                annunciator.Message = Utility.ExceptionReport.GetExceptionInfo(ex, false);
            }
        }

        #endregion

        #region Web Form Designer generated code

        /// <summary>
        /// Handler for the event raised when the page is being initialized.
        /// Retrieve the cache policy and page cache policy in force.
        /// Deposit event handlers to support the datagrid pagination.
        /// </summary>
        /// <param name="e">Argument associated with the event</param>
        protected override void OnInit(EventArgs e)
        {
            cachePolicy = (Policy.ICachePolicy) Session[Policy.Names.CachePolicyKey];
            pageCachePolicy = (Policy.ICachePolicy) Session[Policy.Names.PageCachePolicyKey];

            base.OnInit(e);
        }

        #endregion

        protected void OnSubNavigate(object sender, CommandEventArgs e)
        {
            PurgeCache();
        }

        protected void OnBreadCrumbNavigate(object sender, CommandEventArgs e)
        {
            PurgeCache();
        }

        public void PurgeCache()
        {
            ResultsCache.PurgeObject(cachePolicy);
        }
    }
}